/*
 * Copyright 2010-2020 Gildas Lormeau
 * contact : gildas.lormeau <at> gmail.com
 * 
 * This file is part of SingleFile.
 *
 *   The code in this file is free software: you can redistribute it and/or 
 *   modify it under the terms of the GNU Affero General Public License 
 *   (GNU AGPL) as published by the Free Software Foundation, either version 3
 *   of the License, or (at your option) any later version.
 * 
 *   The code in this file is distributed in the hope that it will be useful, 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 
 *   General Public License for more details.
 *
 *   As additional permission under GNU AGPL version 3 section 7, you may 
 *   distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU 
 *   AGPL normally required by section 4, provided you include this license 
 *   notice and a URL through which recipients can access the Corresponding 
 *   Source.
 */

/* global browser, singlefile, */

singlefile.extension.core.bg.requests = (() => {

	const REQUEST_ID_HEADER_NAME = "x-single-file-request-id";
	const referrers = new Map();
	let referrerOnErrorEnabled = false;

	return {
		REQUEST_ID_HEADER_NAME,
		onMessage,
		setReferrer,
		enableReferrerOnError
	};

	function onMessage(message) {
		if (message.method.endsWith(".enableReferrerOnError")) {
			enableReferrerOnError();
			return {};
		}
		if (message.method.endsWith(".disableReferrerOnError")) {
			disableReferrerOnError();
			return {};
		}
	}

	function setReferrer(requestId, referrer) {
		referrers.set(requestId, referrer);
	}

	function injectRefererHeader(details) {
		if (referrerOnErrorEnabled) {
			let requestIdHeader = details.requestHeaders.find(header => header.name === REQUEST_ID_HEADER_NAME);
			if (requestIdHeader) {
				details.requestHeaders = details.requestHeaders.filter(header => header.name !== REQUEST_ID_HEADER_NAME);
				const referrer = referrers.get(requestIdHeader.value);
				if (referrer) {
					referrers.delete(requestIdHeader.value);
					const header = details.requestHeaders.find(header => header.name.toLowerCase() === "referer");
					if (!header) {
						details.requestHeaders.push({ name: "Referer", value: referrer });
						return { requestHeaders: details.requestHeaders };
					}
				}
			}
		}
	}

	function enableReferrerOnError() {
		if (!referrerOnErrorEnabled) {
			try {
				browser.webRequest.onBeforeSendHeaders.addListener(injectRefererHeader, { urls: ["<all_urls>"] }, ["blocking", "requestHeaders", "extraHeaders"]);
			} catch (error) {
				browser.webRequest.onBeforeSendHeaders.addListener(injectRefererHeader, { urls: ["<all_urls>"] }, ["blocking", "requestHeaders"]);
			}
			referrerOnErrorEnabled = true;
		}
	}

	function disableReferrerOnError() {
		try {
			browser.webRequest.onBeforeSendHeaders.removeListener(injectRefererHeader);
		} catch (error) {
			// ignored
		}
		referrerOnErrorEnabled = false;
	}

})();